package com.gome.ocean.gddl.matrix;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.gome.ocean.common.exception.GddlProcessException;
import com.gome.ocean.dao.model.datax.ScheduledJobTaskVO;
import com.gome.ocean.dao.model.diamond.ConfigInfoBO;
import com.gome.ocean.dao.model.gddl.AppBO;
import com.gome.ocean.service.task.CheckDataSourceJobTask;
import com.gome.ocean.service.task.CheckDataSourceTableJobTask;
import com.gome.ocean.service.task.LoadDatasourceJobTask;
import com.gome.ocean.service.task.MasterSlaveAutoSwitchJobTask;
import com.taobao.tddl.config.impl.ConfigDataHandlerCity;
import com.taobao.tddl.rule.TddlRuleConfig;

/**
 * App 加载服务
 * 
 * @author haqiaolong 2016年3月18日 下午6:06:04
 * @since 5.0.0
 */
@Component
public class GddlAppBean extends GddlAppRuleConfig {

    private static final Logger LOG                            = LoggerFactory.getLogger(GddlAppBean.class);

    private static final String EVERY_THIRTY_SECONDS_CRON      = "30 * * * * ?";                            // 每30秒执行
    private static final String EVERY_FORTY_CRON               = "40 * * * * ?";                            // 每分钟执行
    private static final String EVERY_MINUTE_CRON              = "50 * * * * ?";                           // 每分钟执行
    private static final String EVERY_FIVE_MINUTE_CRON         = "0 */5 * * * ?";                           // 每分钟执行
    private static final String CHECK_DATASOURCE_JOBNAME       = "check_datasource";
    private static final String CHECK_DATASOURCE_TABLE_JOBNAME = "check_datasource_table";
    private static final String LOAD_DATASOURCE                = "load_datasource";
    private static final String DB_AUTO_SWITCH_JOBNAME         = "db_auto_switch";
    private static final String DEFAULT_SYSTEM_GROUP           = "system";

    @Override
    public void afterPropertiesSet() throws Exception {
        final List<ConfigInfoBO> configInfoBOs = configInfoService.findAllApp();
        Thread processThread = new Thread(new Runnable() {
            @Override
            public void run() {
                if (configInfoBOs == null || configInfoBOs.isEmpty()) return;
                for (ConfigInfoBO configInfoBO : configInfoBOs) {
                	try{
                		processApp(configInfoBO);
                	}catch(Exception e){
                		LOG.info("init diamond data is error! dataId = "+ configInfoBO.getDataId());
                		continue;
                	}
                    
                }
            }
        });
        processThread.setUncaughtExceptionHandler(new GddlProcessException());
        processThread.start();
        
        ScheduledJobTaskVO loadDataSource = new ScheduledJobTaskVO();
        loadDataSource.setJobName(LOAD_DATASOURCE);
        loadDataSource.setJobGroup(DEFAULT_SYSTEM_GROUP);
        loadDataSource.setCronExpression(EVERY_THIRTY_SECONDS_CRON);
        if (!schedulerServiceBean.checkExists(loadDataSource)) {
            schedulerServiceBean.addJob(loadDataSource, LoadDatasourceJobTask.class);
            LOG.info("load datasource schedule task is run !!");
        }

        ScheduledJobTaskVO checkDataSrouce = new ScheduledJobTaskVO();
        checkDataSrouce.setJobName(CHECK_DATASOURCE_JOBNAME);
        checkDataSrouce.setJobGroup(DEFAULT_SYSTEM_GROUP);
        checkDataSrouce.setCronExpression(EVERY_FORTY_CRON);
        if (!schedulerServiceBean.checkExists(checkDataSrouce)) {
            schedulerServiceBean.addJob(checkDataSrouce, CheckDataSourceJobTask.class);
            LOG.info("datasource schedule task is run !!");
        }

        ScheduledJobTaskVO checkDataSrouceTable = new ScheduledJobTaskVO();
        checkDataSrouceTable.setJobName(CHECK_DATASOURCE_TABLE_JOBNAME);
        checkDataSrouceTable.setJobGroup(DEFAULT_SYSTEM_GROUP);
        checkDataSrouceTable.setCronExpression(EVERY_FIVE_MINUTE_CRON);//修改 之前为 5分钟，现改为40s zgq
        if (!schedulerServiceBean.checkExists(checkDataSrouceTable)) {
            schedulerServiceBean.addJob(checkDataSrouceTable, CheckDataSourceTableJobTask.class);
            LOG.info("datasource table schedule task is run !!");
        }

        ScheduledJobTaskVO autoSwitchDb = new ScheduledJobTaskVO();
        autoSwitchDb.setJobName(DB_AUTO_SWITCH_JOBNAME);
        autoSwitchDb.setJobGroup(DEFAULT_SYSTEM_GROUP);
        autoSwitchDb.setCronExpression(EVERY_MINUTE_CRON);
        if (!schedulerServiceBean.checkExists(autoSwitchDb)) {
            schedulerServiceBean.addJob(autoSwitchDb, MasterSlaveAutoSwitchJobTask.class);
            LOG.info("auto switch db schedule task is run !!");
        }
    }

    @Override
    public void destroy() {
        
    }

    /**
     * 处理规则
     * 
     * @param configInfoBO
     */
    public void processApp(ConfigInfoBO configInfoBO) {
        String appName = StringUtils.substringBetween(configInfoBO.getDataId(), "com.taobao.tddl.v1_", "_dbgroups");
        AppBO appBO = getAppBO(appName);
        if (appBO != null) {
            // 处理库信息
            processGroup(appBO, configInfoBO);
            // 处理表信息
            // 首先查询版本信息
            ConfigInfoBO versionConfig = configInfoService.findConfigInfoBOByDataId(TddlRuleConfig.getVersionsDataId(appName));
            // 如果不为空代表有版本信息
            if (versionConfig != null) {
                ConfigInfoBO ruleConfig = configInfoService.findConfigInfoBOByDataId(TddlRuleConfig.getVersionedRuleDataId(appName,
                    versionConfig.getContent()));
                if (ruleConfig != null && StringUtils.isNotEmpty(ruleConfig.getContent())) {
                    processApp(appBO, ruleConfig);
                }
            } else {
                ConfigInfoBO ruleConfig = configInfoService.findConfigInfoBOByDataId(TddlRuleConfig.getNonversionedRuledataId(appName));
                if (ruleConfig != null && StringUtils.isNotEmpty(ruleConfig.getContent())) {
                    processApp(appBO, ruleConfig);
                }
            }
            configDataHandlerFactory = ConfigDataHandlerCity.getFactory(appName, unitName);
            configDataHandlerFactory.getConfigDataHandler(configInfoBO.getDataId(), new DbGroupsListener()); // 注册dataId监听
        }
    }
}
